Python | 更新Python后如何修复virtualenv
摘要:在升级了Python后,由于Python路径变更,virtualenv中的symlinks将被破坏,本文提供了脚本来修复这个问题。
01. 运行环境和问题原因
在MBP上,我使用的是Homebrew安装的Python2和Python3,使用virtuanenvwrapper
管理Python的虚拟环境(虚拟环境保存位置$WORKON_HOME=$HOME/.virtualenvs
)。
当brew更新了Python后,再次进入虚拟环境并运行Python时会得到类似如下的错误:
dyld: Library not loaded: @executable_path/../.Python
Referenced from: /your/home/.virtualenvs/virtualenv_name/bin/python
Reason: image not found
执行ls -la ~/.virtualenvs/virtualenv_name/.Python
会发现
/your/home/.virtualenvs/virtualenv_name/.Python -> /usr/local/Cellar/python@2/2.7.XX_X/Frameworks/Python.framework/Versions/2.7/Python
virtualenv崩溃的原因在于,由于symlinks的路径包含了版本号,更新之后会导致symlinks失效。
02. 解决办法
参考StackOverflow中的相关问题后,发现利用下面的语句可以修复virtuanenv中损坏的symlinks
find ~/.virtualenvs/virtualenv_name/ -type l -delete
virtualenv ~/.virtualenvs/virtualenv_name
或者
gfind ~/.virtualenvs/virtualenv_name/ -type l -xtype l -delete
virtualenv ~/.virtualenvs/virtualenv_name
不过,如果你有较多的虚拟环境,挨个更新就显得非常繁琐。更重要的问题是,如果你的虚拟环境中使用的Python版本既有Python2也有Python3,还有些虚拟环境包含了系统全局的packages,第二条语句就得加上参数-p pythonX
和--system-site-packages
。
为了彻底解决这个烦恼,尝试编写脚本来修复virtuanenv。为了判定如何重新创建虚拟环境,做了如下规定:
- 在文件名的末尾通过
2
和3
来区分虚拟环境中Python的版本(要求文件名中间不包含这两个数字),例如Jupyter2
和Jupyter3
; - 在文件名的末尾加上
@
来表示包含系统全局的packages,例如Jupyter2@
。
脚本的思路为:
- 执行virtualenvwrapper.sh(为了能够执行
workon
) - 执行
workon
来获得虚拟环境的列表 - 遍历每个虚拟环境
- 删除该环境中损坏的symlinks
- 根据虚拟环境的名称来确定virtualenv的参数
- 重新创建virtualenv
03. 脚本代码
脚本的代码如下,代码也可以在我的Github中查看。
#!/bin/bash
source virtualenvwrapper.sh
for env_name in $(workon); do
echo ${env_name}
env_path="${WORKON_HOME}/${env_name}"
gfind ${env_path} -type l -xtype l -delete
python_flag=""
if [[ ${env_name} =~ "3" ]]; then
python_flag="-p python3"
else
python_flag="-p python2"
fi
ssp_flag=""
if [[ ${env_name} =~ "@" ]]; then
ssp_flag="--system-site-packages"
fi
echo "virtualenv ${python_flag} ${ssp_flag} ${env_path}"
virtualenv ${python_flag} ${ssp_flag} ${env_path}
done